package nl.hva.three2learn.ui
{
	import flash.display.Sprite;
	import flash.display.Graphics;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.geom.Point;
	import flash.utils.Timer;

	import mx.controls.Alert;
	import mx.events.FlexEvent;

	import spark.components.supportClasses.SkinnableComponent;

	import nl.hva.three2learn.events.BlackboardEvent;

	public class Blackboard extends SkinnableComponent
	{
		private static const ANIMATION_INTERVAL:Number = 20;
	
		[SkinPart(required="true")]
		public var drawArea:Sprite;
	
		[Bindable]
		public var drawingEnabled:Boolean = true;
	
		private var _prevX:Number;
		private var _prevY:Number;
	
		private var _currentLine:Line;
		
		private var _lines:Array;
	
		private var _animationQueue:Array;
		private var _animatingLine:Line;
		private var _animationTimer:Timer;
	
		public function Blackboard()
		{
			super();
			
			_lines = [ ];

			_animationQueue = [ ];
			_animationTimer = new Timer(ANIMATION_INTERVAL);
			_animationTimer.addEventListener(TimerEvent.TIMER, onAnimationTick);

			mouseEnabled = false;

			setStyle("skinClass", BlackboardSkin);
			
			addEventListener(FlexEvent.ADD, onAdd);
		}
		
		public function addLine(line:Line, animate:Boolean = false):void
		{
			// Don't animate the drawing, just slap it on there	
			if (!animate)
			{
				_lines.push(line);
				invalidateDisplayList();
			}
			else
			{
				_animationQueue.push(line);
				
				// No animation currently running, start it up!
				if (!_animationTimer.running)
				{
					_animatingLine = _animationQueue.shift() as Line;
				
					_animationTimer.start();
				}
			}
		}
		
		public function clear():void
		{
			_lines = [ ];
		
			dispatchEvent(new BlackboardEvent(BlackboardEvent.CLEAR));
		
			invalidateDisplayList();
		}
		
		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
		{
			super.updateDisplayList(unscaledWidth, unscaledHeight);
			
			var graphics:Graphics = drawArea.graphics;
			
			// Clear the canvas and set the line style
			graphics.clear();
			graphics.lineStyle(4, 0x000000, 1);
			
			// Draw the lines on to the canvas
			draw(graphics);
		}
		
		private function draw(graphics:Graphics):void
		{			
			for each (var line:Line in _lines)
			{
				line.draw(graphics);
			}			
		}
		
		private function onAnimationTick(e:TimerEvent):void
		{
			_animationTimer.stop();
		
			// Draw a max of 3 points each tick
			for (var i:int = 0; i < 3 && _animatingLine.drawNextPoint(drawArea.graphics); i++)
				;
		
			// And maybe an additional one
			if (!_animatingLine.drawNextPoint(drawArea.graphics))
			{
				// Current line is done drawing
				// add it the to the lines that've been drawn
				_lines.push(_animatingLine);
			
				// Check if there is another line that might need drawing
				_animatingLine = _animationQueue.length > 0 ? (_animationQueue.shift() as Line) : null;
			}
		
			if (_animatingLine !== null)
			{
				// More lines left to go
				_animationTimer.start();
			}
		}
		
		private function onAdd(e:FlexEvent):void
		{
			if (drawingEnabled)
			{
				addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
				addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
				addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
			}
			
			removeEventListener(FlexEvent.ADD, onAdd);
		}
		
		private function onMouseUp(e:MouseEvent):void
		{	
			removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
			
			dispatchEvent(new BlackboardEvent(BlackboardEvent.NEW_LINE, _currentLine.points));
			
			invalidateDisplayList();
		}
		
		private function onMouseDown(e:MouseEvent):void
		{
			if (!drawingEnabled)
			{
				removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
				return;
			}				
		
			_currentLine = new Line();
			_currentLine.addPoint(new Point(e.localX, e.localY));
		
			_lines.push(_currentLine);
		
			addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
		}
		
		private function onMouseMove(e:MouseEvent):void
		{
			_currentLine.addPoint(new Point(e.localX, e.localY));
			
			invalidateDisplayList();
		}
	}
}
